
package com.crowdfunding.circle.user.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.mail.HtmlEmail;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSONObject;
import com.crowdfunding.circle.common.controller.BaseController;
import com.crowdfunding.circle.common.param.SessionUserInfo;
import com.crowdfunding.circle.config.ConfigUtils;
import com.crowdfunding.circle.constant.PageIdEnum;
import com.crowdfunding.circle.permission.service.PermissionService;
import com.crowdfunding.circle.permission.service.RoleService;
import com.crowdfunding.circle.user.entity.UserInfoVO;
import com.crowdfunding.circle.user.service.TokenService;
import com.crowdfunding.circle.user.service.UserInfoService;

/**
 * 密码找回Controller
 *
 * @author 朱国军
 * @since 1.0
 * @version 2016年4月25日 朱国军
 */
@Controller
public class FindPasswordController extends BaseController {
    
    private static final String FIND_PASSWORD_FIRST_PAGE = "/login/find_password_first_step";
    
    private static final String FIND_PASSWORD_SECOND_PAGE = "/login/find_password_second_step";
    
    private Logger logger = LoggerFactory.getLogger(UserInfoController.class);
    
    @Autowired
    private UserInfoService userInfoService;
    
    @Autowired
    private RoleService roleService;
    
    @Autowired
    private TokenService tokenService;
    
    @Autowired
    private PermissionService permissionService;
    
    @RequestMapping(value = "/uncheck/findPassword/firstStep")
    public ModelAndView firstStep() {
        return new ModelAndView(FIND_PASSWORD_FIRST_PAGE);
    }
    
    @RequestMapping(value = "/uncheck/findPassword/doFind", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public String doFind(String userAccount, String imageCode) {
        JSONObject result = new JSONObject();
        
        if (StringUtils.isBlank(imageCode)) {
            result.put("result", false);
            result.put("msg", "图片验证码不能为空");
            return result.toString();
        }
        
        if (StringUtils.isBlank(userAccount)) {
            result.put("result", false);
            result.put("msg", "帐号不能为空");
            return result.toString();
        }
        
        String sessionImageCode = String.valueOf(session.getAttribute(PageIdEnum.FIND_PASSWORD_FIRST.getId() + "_imageCode"));
        
        if (!StringUtils.equals(imageCode, sessionImageCode) || StringUtils.isBlank(sessionImageCode)) {
            result.put("result", false);
            result.put("msg", "图片验证码不正确");
            return result.toString();
        }
        List<UserInfoVO> userList = userInfoService.queryUserByName(null, userAccount);
        UserInfoVO userInfo = new UserInfoVO();
        if (userList == null || userList.size() != 1) {
            result.put("result", false);
            result.put("msg", "用户不存在");
            return result.toString();
        } else {
            userInfo = userList.get(0);
            if (StringUtils.isBlank(userInfo.getEmail())) {
                result.put("result", false);
                result.put("msg", "没有填写邮箱，不能进行找回密码");
                return result.toString();
            }
        }
        
        String tokenId = tokenService.createToken(userInfo.getUserId(), 900000L);
        if (StringUtils.isBlank(tokenId) || StringUtils.equals(tokenId, "-1")) {
            result.put("result", false);
            result.put("msg", "重置邮件15分钟内只能发送一次");
            return result.toJSONString();
        } else if (StringUtils.equals(tokenId, "-2")) {
            result.put("result", false);
            result.put("msg", "发送邮件时生成token失败");
            return result.toJSONString();
        } else {
            if (sendMail(tokenId, userInfo.getEmail())) {
                result.put("result", true);
                result.put("msg", "发送邮件成功");
                return result.toJSONString();
            } else {
                result.put("result", false);
                result.put("msg", "发送邮件失败");
                return result.toJSONString();
            }
        }
    }

    /**
     * 发送找回密码的邮件
     *
     * @param tokenId
     * @param toMail
     * @return
     */
    private Boolean sendMail(String tokenId, String toMail) {
        try {
            HtmlEmail email = new HtmlEmail();
            email.setHostName(ConfigUtils.getStringValueByKey("mail.hostName"));
            email.setAuthentication(ConfigUtils.getStringValueByKey("mail.userName"), ConfigUtils.getStringValueByKey("mail.password"));
            email.setCharset("utf-8");
            email.addTo(toMail, StringUtils.substringBefore(toMail, "@"), "utf-8");
            String fromMail = ConfigUtils.getStringValueByKey("mail.fromMail");
            email.setFrom(fromMail, "嗮羊毛", "utf-8");
            email.setSubject("嗮羊毛密码找回");
            // 设置html内容，实际使用时可以从文本读入写好的html代码
            StringBuffer htmlMsg = new StringBuffer(128);
            htmlMsg.append("<p style='text-align:center;'>");
            htmlMsg.append("<span style='line-height:1.5;font-size:18px;'>请通过以下连接找回密码</span></p>");
            htmlMsg.append("<p style='text-align:center;'>");
            htmlMsg.append("<span style='line-height:1.5;font-size:18px;'>");
            
            String fullPath = getPath() + "/uncheck/findPassword/secondStep?token=" + tokenId;
            
            htmlMsg.append("<a href='" + fullPath + "' target='_blank'>");
            htmlMsg.append(fullPath + "</a></span></p>");
            htmlMsg.append("<p style='text-align:center;'><br /></p>");
            htmlMsg.append("<p style='text-align:center;'><br /></p>");
            htmlMsg.append("<p style='text-align:center;'>");
            htmlMsg.append("<span style='color:#666666;font-family:'Microsoft Yahei', '冬青黑体简体中文 w3', 宋体;");
            htmlMsg.append("font-size:13px;line-height:18.5714px;background-color:#FFFFFF;'>");
            htmlMsg.append("深圳市晒羊毛互联网信息咨询有限公司</span>");
            htmlMsg.append("</p>");
            email.setHtmlMsg(htmlMsg.toString());
            
            email.send();
            return true;
        } catch (Exception e) {
            logger.error("邮件发送失败", e);
            
            return false;
        }
        
    }

    @RequestMapping(value = "/uncheck/findPassword/secondStep")
    public ModelAndView secondStep(String token) {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        // token2个小时有效
        String userId = tokenService.validToken(token, 7200000L);
        if (StringUtils.isBlank(userId) || StringUtils.equals(userId, "-1")) {
            resultMap.put("result", userId);
            resultMap.put("msg", "token过期，请重新请求");
        } else if (StringUtils.equals(userId, "-2")) {
            resultMap.put("result", userId);
            resultMap.put("msg", "token不存在");
        } else {
            UserInfoVO userInfo = userInfoService.findById(userId);

            if (userInfo == null) {
                resultMap.put("result", "-3");
                resultMap.put("msg", "根据token找不到对应用户");
            } else {
                SessionUserInfo sessionUserInfo = new SessionUserInfo();
                sessionUserInfo.setUserId(userId);
                sessionUserInfo.setUserName(userInfo.getUserName());

                sessionUserInfo.setUserInfo(userInfo);

                sessionUserInfo.setPermissionList(permissionService.queryPermissionByUserId(userId));
                sessionUserInfo.setRoleList(roleService.queryRoleByUserId(userId));

                session.setAttribute("sessionUserInfo", sessionUserInfo);
                resultMap.put("result", "0");
                resultMap.put("msg", "token验证成功");
            }
        }
        return new ModelAndView(FIND_PASSWORD_SECOND_PAGE, resultMap);
    }
    
    @RequestMapping(value = "/check/findPassword/reset", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public String findPassword(String userPassword, String confirmPassword, String imageCode) {
        SessionUserInfo seUser = (SessionUserInfo) session.getAttribute("sessionUserInfo");
        
        JSONObject result = new JSONObject();
        
        if (StringUtils.isBlank(userPassword) || StringUtils.isBlank(confirmPassword)) {
            result.put("result", false);
            result.put("msg", "用户密码不能为空");
            return result.toString();
        }
        
        if (StringUtils.isBlank(imageCode)) {
            result.put("result", false);
            result.put("msg", "图片验证码不能为空");
            return result.toString();
        }
        
        String sessionImageCode = String.valueOf(session.getAttribute(PageIdEnum.FIND_PASSWORD_SECOND.getId() + "_imageCode"));
        
        if (!StringUtils.equals(imageCode, sessionImageCode) || StringUtils.isBlank(sessionImageCode)) {
            result.put("result", false);
            result.put("msg", "图片验证码不正确");
            return result.toString();
        }
        
        if (!StringUtils.equals(userPassword, confirmPassword)) {
            result.put("result", false);
            result.put("msg", "两次输入的密码不一致");
            return result.toString();
        }
        
        String userPasswordPattern = "^[a-zA-Z0-9_]{6,15}$";
        if (!Pattern.matches(userPasswordPattern, userPassword)) {
            result.put("result", false);
            result.put("msg", "密码不符合规范，密码长度6到15位，允许输入字幕、数字、_");
            return result.toString();
        }
        
        UserInfoVO userInfoVO = new UserInfoVO();
        userInfoVO.setUserId(seUser.getUserId());
        userInfoVO.setUserPassword(userPassword);
        try {
            Integer updateCount = userInfoService.update(userInfoVO);
            if (updateCount != null && updateCount == 1) {
                result.put("result", true);
                result.put("message", "重置用户密码成功");
            } else {
                result.put("result", false);
                result.put("message", "重置用户密码失败");
            }
        } catch (Exception e) {
            logger.error("重置用户密码出错", e);
            result.put("result", false);
            result.put("message", "重置用户密码出错：" + e.getLocalizedMessage());
        }
        return result.toJSONString();
    }
    
}
